/**
******************************************************************************
* @file    usbh_hcs.c
* @author  MCD Application Team
* @version V2.2.0
* @date    09-November-2015
* @brief   This file implements functions for opening and closing host channels
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
*        http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/

#include "usbh_hcs.h"

static uint16_t USBH_GetFreeChannel (USB_OTG_CORE_HANDLE *pdev);

/**
 * @brief  USBH_Open_Channel
 *         Open a  pipe
 * @param  pdev : Selected device
 * @param  hc_num: Host channel Number
 * @param  dev_address: USB Device address allocated to attached device
 * @param  speed : USB device speed (Full/Low)
 * @param  ep_type: end point type (Bulk/int/ctl)
 * @param  mps: max pkt size
 * @retval Status
 */
uint8_t USBH_Open_Channel  (USB_OTG_CORE_HANDLE *pdev,
                            uint8_t hc_num,
                            uint8_t dev_address,
                            uint8_t speed,
                            uint8_t ep_type,
                            uint16_t mps)
{

    pdev->host.hc[hc_num].ep_num = pdev->host.channel[hc_num]& 0x7F;
    pdev->host.hc[hc_num].ep_is_in = (pdev->host.channel[hc_num] & 0x80 ) == 0x80;
    pdev->host.hc[hc_num].dev_addr = dev_address;
    pdev->host.hc[hc_num].ep_type = ep_type;
    pdev->host.hc[hc_num].max_packet = mps;
    pdev->host.hc[hc_num].speed = speed;
    pdev->host.hc[hc_num].toggle_in = 0;
    pdev->host.hc[hc_num].toggle_out = 0;
    if(speed == HPRT0_PRTSPD_HIGH_SPEED)
    {
        pdev->host.hc[hc_num].do_ping = 1;
    }

    USB_OTG_HC_Init(pdev, hc_num) ;

    return HC_OK;

}

/**
 * @brief  USBH_Modify_Channel
 *         Modify a  pipe
 * @param  pdev : Selected device
 * @param  hc_num: Host channel Number
 * @param  dev_address: USB Device address allocated to attached device
 * @param  speed : USB device speed (Full/Low)
 * @param  ep_type: end point type (Bulk/int/ctl)
 * @param  mps: max pkt size
 * @retval Status
 */
uint8_t USBH_Modify_Channel (USB_OTG_CORE_HANDLE *pdev,
                             uint8_t hc_num,
                             uint8_t dev_address,
                             uint8_t speed,
                             uint8_t ep_type,
                             uint16_t mps)
{

    if(dev_address != 0)
    {
        pdev->host.hc[hc_num].dev_addr = dev_address;
    }

    if((pdev->host.hc[hc_num].max_packet != mps) && (mps != 0))
    {
        pdev->host.hc[hc_num].max_packet = mps;
    }

    if((pdev->host.hc[hc_num].speed != speed ) && (speed != 0 ))
    {
        pdev->host.hc[hc_num].speed = speed;
    }

    USB_OTG_HC_Init(pdev, hc_num);
    return HC_OK;

}

/**
 * @brief  USBH_Alloc_Channel
 *         Allocate a new channel for the pipe
 * @param  ep_addr: End point for which the channel to be allocated
 * @retval hc_num: Host channel number
 */
uint8_t USBH_Alloc_Channel  (USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr)
{
    uint16_t hc_num;

    hc_num =  USBH_GetFreeChannel(pdev);

    if (hc_num != HC_ERROR)
    {
	pdev->host.channel[hc_num] = HC_USED | ep_addr;
    }
    return hc_num;
}

/**
 * @brief  USBH_Free_Pipe
 *         Free the USB host channel
 * @param  idx: Channel number to be freed
 * @retval Status
 */
uint8_t USBH_Free_Channel  (USB_OTG_CORE_HANDLE *pdev, uint8_t idx)
{
    if(idx < HC_MAX)
    {
        pdev->host.channel[idx] &= HC_USED_MASK;
    }
    return USBH_OK;
}


/**
 * @brief  USBH_DeAllocate_AllChannel
 *         Free all USB host channel
 * @param  pdev : core instance
 * @retval Status
 */
uint8_t USBH_DeAllocate_AllChannel  (USB_OTG_CORE_HANDLE *pdev)
{
    uint8_t idx;

    for (idx = 2; idx < HC_MAX ; idx ++)
    {
        pdev->host.channel[idx] = 0;
    }
    return USBH_OK;
}

/**
 * @brief  USBH_GetFreeChannel
 *         Get a free channel number for allocation to a device endpoint
 * @param  None
 * @retval idx: Free Channel number
 */
static uint16_t USBH_GetFreeChannel (USB_OTG_CORE_HANDLE *pdev)
{
    uint8_t idx = 0;

    for (idx = 0 ; idx < HC_MAX ; idx++)
    {
	if ((pdev->host.channel[idx] & HC_USED) == 0)
	{
            return idx;
	}
    }
    return HC_ERROR;
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
